﻿using StackExchange.Redis;
using MySqlSync.Core.Interfaces;
using MySqlSync.Core.Models;
using System;
using System.Threading.Tasks;

namespace MySqlSync.Redis
{
    /// <summary>
    /// Redis服务实现
    /// </summary>
    public class RedisService : IRedisService
    {
        private readonly IDatabase _database;
        private readonly ConnectionMultiplexer _connection;
        private bool _isDisposed = false;

        /// <summary>
        /// 构造函数
        /// </summary>
        public RedisService(RedisConfig config)
        {
            if (config == null)
                throw new ArgumentNullException(nameof(config));

            if (string.IsNullOrEmpty(config.ConnectionString))
                throw new ArgumentException("Redis连接字符串不能为空", nameof(config));

            _connection = ConnectionMultiplexer.Connect(config.ConnectionString);
            _database = _connection.GetDatabase(config.Database);

            // 注册连接事件
            _connection.ConnectionFailed += (sender, args) =>
                Console.WriteLine($"Redis连接失败: {args.Exception.Message}");

            _connection.ConnectionRestored += (sender, args) =>
                Console.WriteLine("Redis连接已恢复");
        }

        /// <summary>
        /// 获取最后同步时间
        /// </summary>
        public async Task<DateTime> GetLastSyncTimeAsync(string tableName)
        {
            if (string.IsNullOrEmpty(tableName))
                throw new ArgumentNullException(nameof(tableName));

            CheckDisposed();

            var key = $"sync:lastSyncTime:{tableName}";
            var value = await _database.StringGetAsync(key);

            if (value.HasValue && DateTime.TryParse(value, out var time))
                return time;

            // 默认返回一个较早的时间，表示需要同步所有数据
            return DateTime.UnixEpoch;
        }

        /// <summary>
        /// 设置最后同步时间
        /// </summary>
        public async Task SetLastSyncTimeAsync(string tableName, DateTime time)
        {
            if (string.IsNullOrEmpty(tableName))
                throw new ArgumentNullException(nameof(tableName));

            CheckDisposed();

            var key = $"sync:lastSyncTime:{tableName}";
            // 使用ISO 8601格式存储，确保跨平台兼容性
            await _database.StringSetAsync(key, time.ToString("o"));
        }

        /// <summary>
        /// 获取最后同步的ID
        /// </summary>
        public async Task<long> GetLastSyncIdAsync(string tableName)
        {
            if (string.IsNullOrEmpty(tableName))
                throw new ArgumentNullException(nameof(tableName));

            CheckDisposed();

            var key = $"sync:lastSyncId:{tableName}";
            var value = await _database.StringGetAsync(key);

            if (value.HasValue && long.TryParse(value, out var id))
                return id;

            return 0;
        }

        /// <summary>
        /// 设置最后同步的ID
        /// </summary>
        public async Task SetLastSyncIdAsync(string tableName, long id)
        {
            if (string.IsNullOrEmpty(tableName))
                throw new ArgumentNullException(nameof(tableName));

            CheckDisposed();

            var key = $"sync:lastSyncId:{tableName}";
            await _database.StringSetAsync(key, id.ToString());
        }

        /// <summary>
        /// 检查是否已完成全量同步
        /// </summary>
        public async Task<bool> IsFullSyncCompletedAsync(string tableName)
        {
            if (string.IsNullOrEmpty(tableName))
                throw new ArgumentNullException(nameof(tableName));

            CheckDisposed();

            var key = $"sync:fullSyncCompleted:{tableName}";
            var value = await _database.StringGetAsync(key);
            return value.HasValue && value.ToString().Equals("1", StringComparison.OrdinalIgnoreCase);
        }

        /// <summary>
        /// 设置全量同步完成状态
        /// </summary>
        public async Task SetFullSyncCompletedAsync(string tableName, bool completed)
        {
            if (string.IsNullOrEmpty(tableName))
                throw new ArgumentNullException(nameof(tableName));

            CheckDisposed();

            var key = $"sync:fullSyncCompleted:{tableName}";
            await _database.StringSetAsync(key, completed ? "1" : "0");
        }

        /// <summary>
        /// 检查是否已释放
        /// </summary>
        private void CheckDisposed()
        {
            if (_isDisposed)
                throw new ObjectDisposedException(nameof(RedisService));
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            if (!_isDisposed)
            {
                _connection?.Dispose();
                _isDisposed = true;
            }
        }
    }

}
